import { Injectable } from '@angular/core'
import { Observable, throwError, forkJoin } from 'rxjs'
import { catchError, map } from 'rxjs/operators'
import { HttpClient } from '@angular/common/http'

import { COMB_URL } from 'app/utils/contraints'
import {
  ITradeQueryParams,
  ITradePagination,
  ITrade,
  ITradeDetailQueryParams,
  ITradeStatisticQueryParams,
  ITradeStatisticPagination,
  ITradeOnlineChargeQueryParams,
  ITradeOnlineChargePagination,
  OnlineChargeAddModel,
  ITradeOnlineCharge,
  StoreInfo,
  ECategoryUrl,
  ITradeRefund,
  ITradeManualVoid,
} from '@shared/interfaces/trade'
import { encodeParams, preProcessParams } from '@shared/decorators'
import { TradeService } from './trade-abstract.service'
import { AmountStr2int } from 'app/utils/helpers'
import { CurrencyService } from '@shared/services/currency.service'
import { IReportResponse } from '@shared/interfaces/response'

enum ECategoryMap {
  'qr' = 'zebra',
  'card' = 'turtle',
}

@Injectable()
export class TradeAlinterService implements TradeService {
  constructor(private http: HttpClient, private currencyService: CurrencyService) {}

  @preProcessParams()
  @encodeParams()
  getList(params: ITradeQueryParams, str?: string): Observable<ITradePagination> {
    const url = `${COMB_URL}/camel/trades?${str}`
    return this.http.get<ITradePagination>(url)
  }

  @preProcessParams()
  @encodeParams()
  getTransList(
    params: ITradeQueryParams,
    intStoreCode: string,
    batchNum: string,
    str?: string,
  ): Observable<ITradePagination> {
    const url = `${COMB_URL}/turtle/trades/batchfind/${intStoreCode}/${batchNum}?${str}`
    return this.http.get<ITradePagination>(url)
  }

  getOne(params: ITradeDetailQueryParams, category = ECategoryUrl.card): Observable<ITrade> {
    const { intStoreCode, orderNum } = params
    const url = `${COMB_URL}/${category}/trade/${intStoreCode}/${orderNum}`
    return this.http.get<ITrade>(url, { withCredentials: true })
  }

  /** 获取交易统计列表 */
  @preProcessParams()
  @encodeParams()
  getTradeStatistics(params: ITradeStatisticQueryParams, str?: string): Observable<ITradeStatisticPagination> {
    const url = `${COMB_URL}/camel/trade/statistics?${str}`
    return this.http.get<ITradeStatisticPagination>(url).pipe(catchError(err => throwError(err)))
  }

  /** 获取交易统计下载链接 */
  @preProcessParams()
  @encodeParams()
  getTradeStatisticsReport(
    params: ITradeStatisticQueryParams,
    str?: string,
  ): Observable<IReportResponse> {
    const url = `${COMB_URL}/camel/trade/statistics/report?${str}`
    return this.http.get<IReportResponse>(url)
  }

  /** 获取交易列表下载链接 */
  @preProcessParams()
  @encodeParams()
  getTradeListReport(params: ITradeStatisticQueryParams, str?: string): Observable<IReportResponse> {
    const url = `${COMB_URL}/camel/trades/report?${str}`
    return this.http.get<IReportResponse>(url)
  }

  /** 获取在线收款列表 */
  @preProcessParams()
  @encodeParams()
  public getTradeOnlineCharge(
    params: ITradeOnlineChargeQueryParams,
    str?: string,
  ): Observable<ITradeOnlineChargePagination> {
    const url = `${COMB_URL}/camel/orders?${str}`
    return this.http.get<ITradeOnlineChargePagination>(url).pipe(catchError(err => throwError(err)))
  }

  public createOnlineChargeOrder(params: OnlineChargeAddModel): Observable<any> {
    const url = `${COMB_URL}/camel/order`
    const decimal = +params.orderInfo.currency.decimal
    const req = {
      intStoreCode: params.systemInfo.intStoreCode,
      commodity: params.orderInfo.commodity,
      amount: AmountStr2int(String(params.orderInfo.amount), decimal),
      currency: params.orderInfo.currency.code,
      remark: params.orderInfo.description,
      duration: parseInt(params.orderInfo.duration, 10),
    }
    return this.http.post<any>(url, req).pipe(catchError(err => throwError(err)))
  }

  public getChargeDetail(chargeId: string): Observable<ITradeOnlineCharge> {
    const url = `${COMB_URL}/camel/order/${chargeId}`
    return this.http.get<ITradeOnlineCharge>(url).pipe(catchError(err => throwError(err)))
  }

  /** 根据门店编码获取门店信息 */
  public getStoreInfo(intStoreCode: string): Observable<StoreInfo> {
    const url = `${COMB_URL}/camel/store/${intStoreCode}`
    return this.http.get<StoreInfo>(url).pipe(
      map((res: any) => res.common),
      catchError(err => throwError(err)),
    )
  }

  /** 获取带有币种信息的在线收款列表 */
  public getTradeOnlineChargeWithCurrency(queryParams: ITradeOnlineChargeQueryParams, str?: string): Observable<any> {
    return forkJoin(this.currencyService.getList(), this.getTradeOnlineCharge(queryParams, str))
  }

  /** 获取带有币种信息的在线收款详情 */
  public getChargeDetailWithCurrency(chargeId: string): Observable<any> {
    return forkJoin(this.currencyService.getList(), this.getChargeDetail(chargeId))
  }

  /** 商户退款 */
  merchantRefund(data: ITradeRefund): Observable<boolean> {
    const url = `${COMB_URL}/camel/rfdp`
    return this.http.post<boolean>(url, data)
  }

  /** 手工退款 */
  manualRefund(data: ITradeRefund): Observable<boolean> {
    const url = `${COMB_URL}/camel/refd`
    return this.http.post<boolean>(url, data)
  }

  /** ecPay手工退款 */
  ecPayManualRefund(data: ITradeRefund): Observable<boolean> {
    const url = `${COMB_URL}/camel/ecrefd`
    return this.http.post<boolean>(url, data)
  }

  /** 手工请款 */
  manualPresent(data): Observable<boolean> {
    const url = `${COMB_URL}/turtle/trade/manualtrans`
    return this.http.post<boolean>(url, data)
  }

  /** 手工撤销 */
  manualVoid(data: ITradeManualVoid): Observable<boolean> {
    const url = `${COMB_URL}/turtle/trade/rvctmanual`
    return this.http.post<boolean>(url, data).pipe(
      map(
        res => true,
        catchError(err => throwError(err))
      )
    )
  }
}
